package com.ra.landlord;

import java.io.File;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Index;
import org.hibernate.annotations.Where;

import com.espirit.eap.ICheckModelDuplicateInfo;
import com.espirit.eap.sa.LoginUser;
import com.googlecode.cswish.annotation.cm;
import com.ra.system.Register;
import com.ra.system.Version;
import com.ra.util.Address;

/**
 * 房东，房东管理员， 客服，超级管理员<br>
 * 其角色借助LandlordPermission.type(administrator.admin_type)区分
 * 
 * @author Jerry
 *
 */
@Entity
@Table(name = "ra_landlordpermission")
@SecondaryTable(name = "ra_landlorduser", pkJoinColumns=@PrimaryKeyJoinColumn(name="user_id"))
@DiscriminatorColumn(name = "admin_type", discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("0")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
// 4 - 房东， 6 - VIP房东, 8 - 房东管理员
@Where(clause = "admin_type = 4 or admin_type = 6 or admin_type = 8")
@cm("房东或房东管理员")
public class LandlordUser implements Version, ICheckModelDuplicateInfo, Register {

	private final static String[] UNIQUE_PROPERTIES = new String[] {"phone"};
	
	public final static Integer GENDER_MALE = 1;
	public final static Integer GENDER_FEMALE = 2;
	
	private Integer id;
	
	private Integer vipType;
	
	// 0 - 未知， 1 - 男， 2 - 女
	private Integer gender;
	
	private String password;
	
	private Integer pictureId;
	
	//头像文件名
	private String photoFileName;
	
	//@Transient
	private String photoContentType;
	
	//@Transient
	private File photo;
	
	private String name;
	
	private String idCard;
	
	private String aliase;
	
	private String email;
	
	private String phone;
	
	private String phoneTwo;
	
	// 证件类型
	// 0 - 居住证， 1 - 学生证， 2 - 其它
	private Integer certificateType;
	
	// 证件号
	private String certificate;
	
	private String qq;
	
	private String address;

	private Address detailAddress;
	
	private Date birthday;
	
	private Date register;
	
	private Integer perm;
	
	// 备注
	private String remark;
	
	private LoginUser loginUser;
	
	// 房东管理员
	private List<LandlordUser> administrators;

	// 房东拥有的房屋
	private List<Building> buildings;
	
	// 使用软件类型  TODO: 值未定
	// 1 - 铺位版， 2 - 公寓版， 3 - 写字楼版
	// 0,3,4,7
	private Integer loginType;
	
	// 用户来源: null,0,1 - PC, 2 - 网站, 3 - Android APP, 4 - iPhone , 5 - 线下
	private Integer sourceFrom;
	
	// 用户渠道
	private String sourceChannel;
	
	private Integer version;
	
	private Integer status;
	
	// 房东收租所用的银行卡
	private List<BankCard> bankCards;
	
	private Integer adminType;
	
	// 是否认证
	private Boolean certification;
	
	// 参加百万活动
	// TODO: 将来重构时, 需要结合活动的设计, 去掉这个字段
	private Boolean attendMilliActivity;
	
	private Boolean existWeixinCard;
	
	private Boolean existAlipayCard;
	
	private Boolean existBankCard;
	
	//最新的一次房屋配置
	private List<FeeRuleCfg> latestFeeRuleCfgs;
	
	@Id
	@GeneratedValue
	@Column(name = "user_id")
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
		
		
	}
	
	
	@Column(name = "vip_type")
	public Integer getVipType() {
		return vipType;
	}

	public void setVipType(Integer vipType) {
		this.vipType = vipType;
	}

	@Column(table = "ra_landlorduser", name = "gender")
	public Integer getGender() {
		return gender;
	}

	public void setGender(Integer gender) {
		this.gender = gender;
	}

	@Column(table = "ra_landlorduser", name = "password")
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Column(table = "ra_landlorduser", name = "user_pictures_id")
	public Integer getPictureId() {
		return pictureId;
	}

	public void setPictureId(Integer pictureId) {
		this.pictureId = pictureId;
	}

	@Column(table = "ra_landlorduser", name = "user_name")
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Transient
	public String getDisplayName() {
		String displayName = name;	// 缺省为本名
		if (name != null && name.length() > 0) {
			char firstLetter = name.charAt(0);
			// 不转换全拼音或者不规则的人名
			if (!Character.isUpperCase(firstLetter) && !Character.isLowerCase(firstLetter) && !Character.isDigit(firstLetter)) {
				String genderName = LandlordUser.GENDER_FEMALE.equals(gender) ? "小姐" : "先生";
				displayName = firstLetter + genderName;
			}
		}
		return displayName;
	}

	@Column(table = "ra_landlorduser", name = "user_id_card")
	public String getIdCard() {
		return idCard;
	}

	public void setIdCard(String idCard) {
		this.idCard = idCard;
	}

	@Column(table = "ra_landlorduser", name = "user_aliase")
	public String getAliase() {
		return aliase;
	}

	public void setAliase(String aliase) {
		this.aliase = aliase;
	}

	@Column(table = "ra_landlorduser", name = "user_e_mail")
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Column(table = "ra_landlorduser", name = "user_phone")
	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}
	
	@Column(table = "ra_landlorduser", name = "user_telephone")
	public String getPhoneTwo() {
		return phoneTwo;
	}

	public void setPhoneTwo(String phoneTwo) {
		this.phoneTwo = phoneTwo;
	}

	@Column(table = "ra_landlorduser", name = "certificate_id")
	public Integer getCertificateType() {
		return certificateType;
	}

	public void setCertificateType(Integer certificateType) {
		this.certificateType = certificateType;
	}

	@Column(table = "ra_landlorduser", name = "user_certificate")
	public String getCertificate() {
		return certificate;
	}

	public void setCertificate(String certificate) {
		this.certificate = certificate;
	}

	@Column(table = "ra_landlorduser", name = "user_qq")
	public String getQq() {
		return qq;
	}

	public void setQq(String qq) {
		this.qq = qq;
	}

	@Column(table = "ra_landlorduser", name = "user_address")
	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}
	
	
	@ManyToOne(cascade=CascadeType.MERGE, fetch=FetchType.LAZY, optional=true)
	@JoinColumn(table = "ra_landlorduser", name = "detailAddress_area_id")
	public Address getDetailAddress() {
		return detailAddress;
	}

	public void setDetailAddress(Address detailAddress) {
		this.detailAddress = detailAddress;
	}

	@Column(table = "ra_landlorduser", name = "user_birthday")
	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	@Column(table = "ra_landlorduser", name = "user_Registered")
	@Index(name="idx_ra_landlorduser_user_Registered")
	public Date getRegister() {
		return register;
	}

	public void setRegister(Date register) {
		this.register = register;
	}

	@Column(table = "ra_landlorduser", name = "user_note")
	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	@Column(table = "ra_landlorduser", name = "user_login_type")
	public Integer getLoginType() {
		return loginType;
	}

	public void setLoginType(Integer loginType) {
		this.loginType = loginType;
	}
	
	@Column(name = "perm")
	public Integer getPerm() {
		return perm;
	}

	/**
	 * ADMINISTRATOR_PERM_COMMON		= 0x00000000,			// 无权限
	 * ADMINISTRATOR_PERM_GRANT			= 0x00000001,			// 授权
	 * ADMINISTRATOR_PERM_MAX			= 0x000fffff,			// 所有权限
	 * 
	 * @param perm
	 */
	public void setPerm(Integer perm) {
		this.perm = perm;
	}

	@OneToMany(targetEntity = LandlordUser.class, fetch=FetchType.LAZY,
			cascade=CascadeType.MERGE)
	@JoinTable(name = "ra_landlorduser_landlordpermission", 
		joinColumns = @JoinColumn(name="user_id"),  
		inverseJoinColumns = @JoinColumn(name="administrator_id"))
	public List<LandlordUser> getAdministrators() {
		return administrators;
	}

	public void setAdministrators(List<LandlordUser> administrators) {
		this.administrators = administrators;
	}

	@ManyToMany(targetEntity = Building.class, fetch=FetchType.LAZY, mappedBy="landlordUsers")
	@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
	@Where(clause = "data_status = 1")
	public List<Building> getBuildings() {
		return buildings;
	}

	public void setBuildings(List<Building> buildings) {
		this.buildings = buildings;
	}
	
	
	@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
	@JoinColumn(table = "ra_landlorduser", name = "loginuser_id")
	public LoginUser getLoginUser() {
		return loginUser;
	}

	public void setLoginUser(LoginUser loginUser) {
		this.loginUser = loginUser;
	}

	@Column(table = "ra_landlorduser", name = "version_id")
	public Integer getVersion() {
		return version;
	}	

	public void setVersion(Integer version) {
		this.version = version;
	}

	@Column(table = "ra_landlorduser", name = "data_status")
	public Integer getStatus() {
		return status;
	}

	public void setStatus(Integer status) {
		this.status = status;
	}
	

	@Column(table = "ra_landlorduser", name = "photo_file_name")
	public String getPhotoFileName() {
		return photoFileName;
	}

	public void setPhotoFileName(String photoFileName) {
		this.photoFileName = photoFileName;
	}

	@Column(table = "ra_landlorduser", name = "source_from")
	public Integer getSourceFrom() {
		return sourceFrom;
	}

	public void setSourceFrom(Integer sourceFrom) {
		this.sourceFrom = sourceFrom;
	}

	@Column(table = "ra_landlorduser", name = "source_channel")
	public String getSourceChannel() {
		return sourceChannel;
	}

	public void setSourceChannel(String sourceChannel) {
		this.sourceChannel = sourceChannel;
	}
	
	@Column(name="admin_type", insertable=false, updatable=false)
	public Integer getAdminType() {
		return adminType;
	}

	public void setAdminType(Integer userType) {
		this.adminType = userType;
	}

	@Transient
	public String getPhotoContentType() {
		return photoContentType;
	}

	public void setPhotoContentType(String photoContentType) {
		this.photoContentType = photoContentType;
	}

	@Transient
	public File getPhoto() {
		return photo;
	}

	public void setPhoto(File photo) {
		this.photo = photo;
	}

	@Override
	public String[] gatherProperties() {
		return UNIQUE_PROPERTIES;
	}
	
	@Transient
	public LandlordOwnerUser getOwnerUser() {
		return null;
	}

	@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY, orphanRemoval=true)
	@JoinTable(name="ra_landlorduser_bankcard")
	public List<BankCard> getBankCards() {
		return bankCards;
	}

	public void setBankCards(List<BankCard> bankCards) {
		this.bankCards = bankCards;
	}
	
	@Transient
	public Boolean getExistWeixinCard() {
		//return existCardType(BankCard.CARTTYPE_WEIXIN);
		return existCardType(BankCard.CARTTYPE_BANK);
	}
	
	@Transient
	public Boolean getExistAlipayCard() {
		//return existCardType(BankCard.CARTTYPE_ALIPAY);
		return existCardType(BankCard.CARTTYPE_BANK);
	}

	@Transient
	public Boolean getExistBankCard() {
		return existCardType(BankCard.CARTTYPE_BANK);
	}
	
	public void setExistWeixinCard(Boolean existWeixinCard) {
		this.existWeixinCard = existWeixinCard;
	}

	public void setExistAlipayCard(Boolean existAlipayCard) {
		this.existAlipayCard = existAlipayCard;
	}

	public void setExistBankCard(Boolean existBankCard) {
		this.existBankCard = existBankCard;
	}
	
	@Column(table = "ra_landlorduser", name = "certification")
	public Boolean getCertification() {
		return certification;
	}

	public void setCertification(Boolean certification) {
		this.certification = certification;
	}

	@Column(table = "ra_landlorduser", name = "attendMilliActivity")
	public Boolean getAttendMilliActivity() {
		return attendMilliActivity;
	}

	public void setAttendMilliActivity(Boolean attendMilliActivity) {
		this.attendMilliActivity = attendMilliActivity;
	}

	private boolean existCardType(Integer cardType){
		boolean result = false;
		if (bankCards != null && bankCards.size() > 0) {
			for (BankCard bankCard : bankCards) {
				if (cardType == bankCard.getCartType()) {
					result = true;
					break;
				}
			}
		}
		return result;
	}

	@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	@JoinTable(name = "ra_landlorduser_latestFeeRuleCfgs", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "user_id"), inverseJoinColumns = @JoinColumn(name = "feeRuleCfg_id", referencedColumnName = "FeeItemId"))
	public List<FeeRuleCfg> getLatestFeeRuleCfgs() {
		return latestFeeRuleCfgs;
	}

	public void setLatestFeeRuleCfgs(List<FeeRuleCfg> latestFeeRuleCfgs) {
		this.latestFeeRuleCfgs = latestFeeRuleCfgs;
	}
}